﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using System.Net;
using AutoUpdater.Models;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;

namespace AutoUpdater
{
    public partial class MainForm : Form
    {
        private MainForm _currentFrm;
        private SettingForm _settForm;
        private System.Windows.Forms.DataGridView _dataGridView;
        private string[] _Args;

        private UptBaseModel _modelBase = new UptBaseModel(); //自动更新清单文件缓存对象
        private string _AppVersion; //主程序版本
        private string _AutoUpdateTempPath; //默认文件缓存路径
        private string _AutoUpdateRootPath; //默认配置程序运行当前目录
        private bool _AutoUpdate = false; //自动更新
        private bool _AutoClose = false; //自动关闭
        private bool _AppRestart = false; //重启主程序
        private string _AppLaunchExe = ""; //启动主程序
        private string _ConfigUrl = ""; //配置文件地址
        private bool _InitLocked = false; //初始化标记

        public MainForm()
        {
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterScreen;
            _dataGridView = CreatePanelView(this.panel_view);
            _currentFrm = this;
        }
        public MainForm(string[] args)
        {
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterScreen;
            _dataGridView = CreatePanelView(this.panel_view);
            _currentFrm = this;
            _Args = args;
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            _currentFrm.Invoke(new MAction(() =>
            {
                _currentFrm.ExecActions();
            }));
        }

        /// <summary>
        /// 点击启动更新
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_startupdate_Click(object sender, EventArgs e)
        {
            try
            {
                ReflashDataAndView();

                if (_currentFrm._modelBase.totalFileSize > 0)
                {
                    if (Common.IsProcessRunning(_AppLaunchExe) && MessageBox.Show("主程序正在运行，是否关闭并更新到最新版？", "版本更新", MessageBoxButtons.OKCancel) == DialogResult.OK)
                    {
                        Common.CloseProcess(_AppLaunchExe, out string err);
                        _currentFrm.Invoke(new MAction(() => {
                            Common.CreatDownloadTasks(_currentFrm._modelBase, _AutoUpdateTempPath, new DownloadProgressChangedEventHandler(_currentFrm.client_DownloadProgressChanged), new AsyncCompletedEventHandler(_currentFrm.client_DownloadFileCompleted));
                        }));
                    }
                    else
                    {
                        _currentFrm.Invoke(new MAction(() => {
                            Common.CreatDownloadTasks(_currentFrm._modelBase, _AutoUpdateTempPath, new DownloadProgressChangedEventHandler(_currentFrm.client_DownloadProgressChanged), new AsyncCompletedEventHandler(_currentFrm.client_DownloadFileCompleted));
                        }));
                    }
                }
                else
                {
                    if (MessageBox.Show("当前文件已是最新版，是否重新更新？", "版本更新", MessageBoxButtons.OKCancel) == DialogResult.OK)
                    {
                        Common.CloseProcess(_AppLaunchExe, out string err);
                        _currentFrm.Invoke(new MAction(() => {
                            Common.CreatDownloadTasks(_currentFrm._modelBase, _AutoUpdateTempPath, new DownloadProgressChangedEventHandler(_currentFrm.client_DownloadProgressChanged), new AsyncCompletedEventHandler(_currentFrm.client_DownloadFileCompleted));
                        }));
                    }
                }
            }
            catch (Exception ex)
            {
                _currentFrm.progressbar_all.Text = ex.Message;
            }
        }

        /// <summary>
        /// 快捷键监听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.F3:
                    ShowSettingForm();
                    break;
            }
        }
        private void link_settings_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ShowSettingForm();
        }

        /// <summary>
        /// 刷新待更新文件数据及界面显示
        /// </summary>
        public void ReflashDataAndView()
        {
            try
            {
                if (_currentFrm.Disposing || _currentFrm.IsDisposed) return;

                _currentFrm.SetNoticeText("获取文件清单...");
                
                InitializeArgs(_Args);
                _currentFrm._modelBase = Common.ReadAutoUpdateMapsXml(_ConfigUrl);

                if (_currentFrm._modelBase?.files == null || _currentFrm._modelBase.files.Count == 0)
                {
                    _currentFrm.SetNoticeText("初始化失败！");
                    return;
                }

                _currentFrm.Invoke(new MAction(() =>
                {
                    _currentFrm.btn_OK.Text = "更新";
                    _currentFrm.btn_OK.Enabled = true;
                    _currentFrm.lbl_updateinfo.Text = _currentFrm._modelBase.description ?? "";
                    _currentFrm.lbl_notice.Text = "版本号：" + _currentFrm._modelBase.version ?? "";
                    _currentFrm.lbl_totalFiles.Text = "文件：" + _currentFrm._modelBase.files.Count;
                    _currentFrm.lbl_totalSize.Text = "待下载：" + FileOperate.GetSizeString(_currentFrm._modelBase.totalFileSize);

                    ReloadDgvDataSource(_currentFrm._modelBase);
                }));
            }
            catch (Exception ex)
            {
                _currentFrm.SetNoticeText("连接服务器失败！" + ex.Message);
            }
        }

        #region 下载监听

        /// <summary>
        /// 下载任务 下载完成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (e.UserState != null)
            {
                _currentFrm.SetNoticeText("...");
                var info = e.UserState as FileInfoModel;

                ReloadDgvDataSource(_currentFrm._modelBase);

                Console.WriteLine(info.targetPath);

                _currentFrm._modelBase.updatingCount++;

                if (_currentFrm._modelBase.updatingCount == _currentFrm._modelBase.updateCount)
                {
                    //开始更新处理
                    Common.StartUpgradeProcess(_currentFrm._modelBase, _AutoUpdateRootPath, _AutoUpdateTempPath, _AppLaunchExe, _AppRestart, _AutoClose, false, this);
                    _currentFrm.SetNoticeText("已更新" + _currentFrm._modelBase.updateCount + "个文件");
                    _currentFrm.Invoke(new MAction(() => {
                        _currentFrm.btn_OK.Visible = true;
                        _currentFrm.lbl_Loading.Visible = false;
                    }));
                }
            }
        }
        /// <summary>
        /// 下载任务 下载过程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            if (e.UserState != null)
            {
                _currentFrm.SetNoticeText("正在下载文件...");
                var info = e.UserState as FileInfoModel;

                info.loadprogress = e.ProgressPercentage + "%";

                if (!_currentFrm.Disposing && !_currentFrm.IsDisposed)
                {
                    _currentFrm.Invoke(new MAction(() => {
                        _currentFrm.progressbar_all.Value = e.ProgressPercentage;
                    }));
                }
            }
        }

        #endregion

        #region 私有函数
        private void ExecActions()
        {
            try
            {
                _currentFrm.btn_OK.Visible = false;

                InitializeArgs(_Args);

                if (_InitLocked == false)
                {
                    if (MessageBox.Show("请初始化自动更新配置！", "自动更新", MessageBoxButtons.OKCancel) == DialogResult.OK)
                    {
                        ShowSettingForm();

                        if (!Common.InitLocked) Application.Exit(); //未初始化，退出程序
                    }
                    else
                    {
                        Application.Exit(); //未初始化，退出程序
                    }
                }

                _currentFrm.SetNoticeText("获取文件清单...");

                _currentFrm._modelBase = Common.ReadAutoUpdateMapsXml(_ConfigUrl);

                if (_InitLocked && _modelBase != null)
                {
                    _currentFrm.btn_OK.Visible = true;
                    _currentFrm.ReloadDgvDataSource(_modelBase);
                    _currentFrm.SetNoticeText("待下载：" + FileOperate.GetSizeString(_currentFrm._modelBase.totalFileSize));

                    var hassNewFiles = _currentFrm._modelBase.totalFileSize > 0;
                    if (_AutoUpdate && hassNewFiles) //是否自动更新
                    {
                        if (Common.IsProcessRunning(_AppLaunchExe) && _currentFrm._modelBase.totalFileSize > 0)
                        {
                            if (MessageBox.Show("主程序正在运行，是否关闭并更新到最新版？", "新版本已发布", MessageBoxButtons.OKCancel) == DialogResult.OK)
                            {
                                Common.CloseProcess(_AppLaunchExe, out string err);
                                Common.CreatDownloadTasks(_currentFrm._modelBase, _AutoUpdateTempPath, new DownloadProgressChangedEventHandler(client_DownloadProgressChanged), new AsyncCompletedEventHandler(client_DownloadFileCompleted));
                            }
                            else
                            {
                                hassNewFiles = false;
                            }
                        }
                        else
                        {
                            Common.CreatDownloadTasks(_currentFrm._modelBase, _AutoUpdateTempPath, new DownloadProgressChangedEventHandler(client_DownloadProgressChanged), new AsyncCompletedEventHandler(client_DownloadFileCompleted));
                        }
                    }

                    if (_AppRestart && !hassNewFiles) //重启主程序（无更新时）
                    {
                        if (!string.IsNullOrEmpty(_AppLaunchExe) && !Common.IsProcessRunning(_AppLaunchExe)) Common.StartProcess(_AppLaunchExe, out string err);
                    }

                    if (_AutoClose && !hassNewFiles) //是否自动关闭（无更新时）
                    {
                        _currentFrm?.Close();
                    }
                }
                else
                {
                    _currentFrm.SetNoticeText("初始化失败！");
                }
            }
            catch (Exception ex)
            {
                _currentFrm?.SetNoticeText(ex.Message);
                //ErrorView.ShowText(ex.Message + ex.StackTrace);
            }
        }

        /// <summary>
        /// 解析参数
        /// </summary>
        /// <param name="args"></param>
        private void InitializeArgs(string[] args = null)
        {
            try
            {

                /*
                 * -i <url>     指定配置文件地址 支持http(s)、file、ftp
                 * -d <file>    指定启动主程序绝对路径
                 * -q           启用静默更新（迷你窗体）
                 * -f           启用全自动更新
                 * -e           更新前自动关闭主程序
                 * -r           更新后自动启动主程序
                 */

                _InitLocked = Common.TryGetCommand(args, "-q", out _InitLocked) ? _InitLocked : Common.InitLocked;
                _AutoClose = Common.TryGetCommand(args, "-e", out _AutoClose) ? _AutoClose : Common.AutoClose;
                _AutoUpdate = Common.TryGetCommand(args, "-f", out _AutoUpdate) ? _AutoUpdate : Common.AutoUpdate;
                _AppRestart = Common.TryGetCommand(args, "-r", out _AppRestart) ? _AppRestart : Common.AppRestart;
                _ConfigUrl = Common.TryGetCommand(args, "-i", out _ConfigUrl) ? _ConfigUrl : Common.ConfigUrl;
                _AppLaunchExe = Common.TryGetCommand(args, "-d", out _AppLaunchExe) ? Common.TrailingFilePath(_AppLaunchExe) : Common.TrailingFilePath(Common.AppLaunchExe);
                _AppVersion = Common.AppVersion;
                _AutoUpdateTempPath = Common.AppRootTmp;
                _AutoUpdateRootPath = Common.AppRootPath;
            }
            catch (Exception ex)
            {
                _currentFrm.SetNoticeText("参数解析错误：" + ex.Message);
            }
        }
        /// <summary>
        /// 显示配置窗体
        /// </summary>
        private void ShowSettingForm()
        {
            if (_settForm == null || _settForm.IsDisposed)
            {
                _settForm = new SettingForm();
                _settForm.Owner = this;
                _settForm.ShowDialog();
            }
            else if (_settForm.Visible == false)
            {
                _settForm.Owner = this;
                _settForm.ShowDialog();
            }
        }
        /// <summary>
        /// 显示提示信息
        /// </summary>
        /// <param name="v"></param>
        private void SetNoticeText(string v)
        {
            if (_currentFrm != null && _currentFrm.IsHandleCreated)
            {
                _currentFrm.Invoke(new MAction(() =>
                {
                    _currentFrm.lbl_notice.Text = v;
                }));
            }
        }
        #endregion

        #region 初始化 DataGrid
        /// <summary>
        /// 初始化DataGridView
        /// </summary>
        /// <param name="panel"></param>
        /// <returns></returns>
        private DataGridView CreatePanelView(Panel panel)
        {
            System.Windows.Forms.DataGridView dgv = new System.Windows.Forms.DataGridView();

            #region 右侧滚动条
            System.Windows.Forms.VScrollBar scrollBar = new System.Windows.Forms.VScrollBar();
            //设置scrollBar属性
            scrollBar.Width = 5;
            scrollBar.Maximum = dgv.RowCount;//设scrollBar最大值为dataGridView的行数
            scrollBar.SmallChange = 1;
            scrollBar.LargeChange = 1;
            scrollBar.Dock = DockStyle.Right;//设置scrollBar在父控件的右侧    
            scrollBar.Hide();
            #endregion

            #region DataGridView数据列

            // 文件名
            System.Windows.Forms.DataGridViewTextBoxColumn col_FileName = new System.Windows.Forms.DataGridViewTextBoxColumn();
            col_FileName.DataPropertyName = "fileName";
            col_FileName.HeaderText = "文件名";
            col_FileName.Name = "col_FileName";
            col_FileName.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
            col_FileName.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
            col_FileName.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;

            // 文件大小
            System.Windows.Forms.DataGridViewTextBoxColumn col_FileBytes = new System.Windows.Forms.DataGridViewTextBoxColumn();
            col_FileBytes.DataPropertyName = "fileBytes";
            col_FileBytes.HeaderText = "文件大小";
            col_FileBytes.Name = "col_FileBytes";
            col_FileBytes.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
            col_FileBytes.Width = 70;
            col_FileBytes.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;

            // 文件HASH1
            System.Windows.Forms.DataGridViewTextBoxColumn col_Hash1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
            col_Hash1.DataPropertyName = "hash1";
            col_Hash1.HeaderText = "文件指纹";
            col_Hash1.Name = "col_Hash1";
            col_Hash1.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
            col_Hash1.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
            col_Hash1.Visible = false;

            // 下载进度
            System.Windows.Forms.DataGridViewTextBoxColumn col_Loadprogress = new System.Windows.Forms.DataGridViewTextBoxColumn();
            col_Loadprogress.DataPropertyName = "loadprogress";
            col_Loadprogress.HeaderText = "下载";
            col_Loadprogress.Name = "col_Loadprogress";
            col_Loadprogress.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
            col_Loadprogress.Width = 60;

            System.Windows.Forms.DataGridViewColumn[] columns = new System.Windows.Forms.DataGridViewColumn[] {
                col_FileName, col_FileBytes, col_Hash1, col_Loadprogress
            };
            #endregion

            #region DataGridView设置
            dgv.Name = "AutoUpdateMapsDgv";
            dgv.Dock = DockStyle.Fill;
            dgv.ScrollBars = ScrollBars.Both;
            dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            dgv.MultiSelect = true;
            dgv.BackgroundColor = System.Drawing.Color.Snow;
            dgv.BorderStyle = BorderStyle.None;
            dgv.GridColor = System.Drawing.Color.LightGray;
            dgv.RowHeadersVisible = false;//左侧空白列隐藏
            dgv.AllowUserToResizeColumns = false;//不允许调整列
            dgv.AllowUserToResizeRows = false;//不允许调整行
            dgv.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;//禁止拖动标题行
            dgv.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;//标题行内容在垂直水平方向均居中
            dgv.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;//单元格内容在垂直水平方向均居中
            dgv.ColumnHeadersHeight = 30;//设置列标题行高为30
            dgv.RowTemplate.Height = 23;//设置单元格行高为23
            dgv.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 9, System.Drawing.FontStyle.Bold);
            dgv.RowsDefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 8.2F, System.Drawing.FontStyle.Regular);
            dgv.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;
            dgv.AllowUserToAddRows = false;//不显示添加行

            //添加右侧滚动条
            //dgv.Controls.Add(scrollBar);
            //添加数据列
            dgv.Columns.AddRange(columns);
            #endregion

            panel.Controls.Add(dgv);
            return dgv;
        }

        /// <summary>
        /// 重新数据加载到DataGridView
        /// </summary>
        /// <param name="modelBase"></param>
        private void ReloadDgvDataSource(UptBaseModel modelBase)
        {
            _currentFrm.Invoke(new MAction(() => {
                if (_dataGridView == null) _dataGridView = CreatePanelView(_currentFrm.panel_view);
                List<FileInfoModel_View> temp = new List<FileInfoModel_View>();
                foreach (var item in modelBase.files)
                {
                    FileInfoModel_View info = new FileInfoModel_View();
                    info.hash1 = item.hash1;
                    info.fileName = item.fileName;
                    info.fileBytes = FileOperate.GetSizeString(item.fileBytes);
                    info.loadprogress = item.loadprogress;
                    temp.Add(info);
                }
                _dataGridView.DataSource = temp;
                if (_dataGridView.Rows.Count > 0)
                {
                    _dataGridView.Rows[0].Selected = false;
                }
            }));
        }

        #endregion

        #region 窗体无边框可拖动
        [DllImport("user32.dll")]
        public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wparam, int lparam);
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Button == MouseButtons.Left)//鼠标左键            
            {
                Capture = false;//释放鼠标
                SendMessage(Handle, 0x00A1, 2, 0);//拖动窗体            
            }
        }

        [DllImport("User32.DLL")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
        [DllImport("User32.DLL")]
        public static extern bool ReleaseCapture();
        public const uint WM_SYSCOMMAND = 0x0112;
        public const int SC_MOVE = 61456;
        public const int HTCAPTION = 2;

        private void Control_MouseDown(object sender, MouseEventArgs e)
        {
            ReleaseCapture();
            SendMessage(Handle, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);
        }
        #endregion
    }
}
